package com.qf.realm;

import com.qf.pojo.Menu;
import com.qf.pojo.Role;
import com.qf.pojo.User;
import com.qf.service.MenuService;
import com.qf.service.RoleService;
import com.qf.service.UserService;
import org.apache.ibatis.annotations.Param;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.Set;

/**
 * projectName: wokepase1
 *
 * @author: 强力
 * time: 2021/9/7 11:03
 * description:自定义realm对象,如何进行用户名密码校验
 * 1.从数据库中根据用户名,取出数据库中的用户名密码交给食肉框架管理
 * 2.根据用户名,到数据库取出用户对应的角色和权限对象交给食肉框架管理
 */
public class MyUserRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    @Autowired
    private MenuService menuService;

    @Autowired
    private RoleService roleService;


    /**
     * 用户的用户名,密码输入正确,校验完成后进行赋权操作
     * 根据用户名,到数据库查询这个用户对应的角色和权限,交给shiro管理
     * @param
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection princ) {
        System.out.println("------已登录成功,授予登录用户权限,也就是赋予用户对应的角色能访问的彩蛋2");
       //获取当前登录的用户
        User user = (User) princ.getPrimaryPrincipal();
        //获取当前用户的用户id
        int uid = user.getId();
        //根据用户id查询该用户的角色和权限
        Set<String> role = roleService.findRoleByUid(uid);
        Set<String> menu = menuService.findMenuByUid(uid);
        //创建shiro中的用户权限对象
        SimpleAuthorizationInfo auth= new SimpleAuthorizationInfo();
        //将查询到的角色放入shiro权限对象
        auth.setRoles(role);
        //将查询到的权限集合放入shiro权限对象
        auth.setStringPermissions(menu);
        //返回shiro权限对象
        return auth;
    }

    /**
     *  根据用户在页面输入的用户名,查询数据库中的用户名密码,交给shiro框架
     *  让shiro框架进行对比用户名 密码是否正确
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("-----------------开始检验用户名密码");
        //1.获取用户在浏览器中输入的用户名
        String username = (String) authenticationToken.getPrincipal();
        //2.根据用户在页面输入的用户名,查询数据库获取用户对象
        String  password = new String((char[]) authenticationToken.getPrincipal());
        //3.判断用户对象是否为空,如果为空抛出异常
        User user = userService.findUserByName(username);
        if (user == null) {
            throw new UnknownAccountException("账号不存在请先注册");
        }
        //4.对比数据库中的密码和用户输入的密码是否一样
        if (!password.equals(user.getPassword())){
            throw  new IncorrectCredentialsException("密码错误");
        }

        //5.判断用户状态,1正常,其他为锁定状态
        if (user.getStatus()!=1){
            throw new LockedAccountException("账号被锁定");
        }


        //6.封装shiro中需要的权限对象,包括用户名,密码,以及当前用户对象交给shiro返回
        //第一参数用户名,第二参数密码,第三参数自定义realm名字,通过this获取
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password, this.getName());
        return info;
    }
}
